package org.checkboo.hopefullyengine.sceneelements;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

public class Texture {
	
	private String name;
	private IntBuffer texturePointer;
	private String texImage;
	private MinFilter minFilter;
	private MagFilter magFilter;
	private Wrap wrapS;
	private Wrap wrapT;
	private int width;
	private int height;
	
	public enum MinFilter {NEAREST, LINEAR, NEAREST_MIPMAP_NEAREST, LINEAR_MIPMAP_NEAREST, NEAREST_MIPMAP_LINEAR, LINEAR_MIPMAP_LINEAR};
	public enum MagFilter {NEAREST, LINEAR};
	public enum Wrap {CLAMP, REPEAT};
	
	public Texture(String name, String image, MinFilter minFilter, MagFilter magFilter, Wrap wrapS, Wrap wrapT){
		this.texturePointer = null;
		this.texImage = image;
		this.minFilter = minFilter;
		this.magFilter = magFilter;
		this.wrapS = wrapS;
		this.wrapT = wrapT;
	}
	
	public void loadTexture(){
		texturePointer = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glGenTextures(texturePointer);
    	GL11.glBindTexture(GL11.GL_TEXTURE_2D, texturePointer.get(0));
    	//GL11.glTexEnvf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
    	GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, getGLMinFilter(minFilter));
    	GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, getGLMagFilter(magFilter));
    	GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, getGLWrap(wrapS));
    	GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, getGLWrap(wrapT));
    	
    	
		try {
			File f = new File(this.texImage);
	    	BufferedImage bi;
			bi = ImageIO.read(f);
			
			this.width = bi.getWidth();
			this.height = bi.getHeight();
			
			byte[] raster = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData();
	    	ByteBuffer bb = BufferUtils.createByteBuffer(raster.length);
	    	bb.put(raster).rewind();
	    	//GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, texImage.getWidth(), texImage.getHeight(), 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, bb);
		    GLU.gluBuild2DMipmaps(GL11.GL_TEXTURE_2D, 3, bi.getWidth(), bi.getHeight(), GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, bb);
		    this.texImage = null;
		    System.gc();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
	}
	
	private int getGLMinFilter(MinFilter filter){
		switch(filter){
		case LINEAR: return GL11.GL_LINEAR;
		case NEAREST: return GL11.GL_NEAREST;
		case NEAREST_MIPMAP_NEAREST: return GL11.GL_NEAREST_MIPMAP_NEAREST;
		case NEAREST_MIPMAP_LINEAR: return GL11.GL_NEAREST_MIPMAP_LINEAR;
		case LINEAR_MIPMAP_LINEAR: return GL11.GL_LINEAR_MIPMAP_LINEAR;
		case LINEAR_MIPMAP_NEAREST: return GL11.GL_LINEAR_MIPMAP_NEAREST;
		default: return -1;
		}
	}
	
	private int getGLMagFilter(MagFilter filter){
		switch(filter){
		case LINEAR: return GL11.GL_LINEAR;
		case NEAREST: return GL11.GL_NEAREST;
		default: return -1;
		}
	}
	
	private int getGLWrap(Wrap wrap){
		switch (wrap) {
		case CLAMP: return GL11.GL_CLAMP;
		case REPEAT: return GL11.GL_REPEAT;
		default: return -1;
		}
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getTexturePointer() {
		if(null == this.texturePointer)
			loadTexture();
		return texturePointer.get(0);
	}

	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}
}
